package com.run2code.starter.lock.config;

import com.run2code.starter.lock.DistributedLock;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisOperations;


/**
 * <pre>
 *     这个配置类的主要目的是自定义RedissonClient的配置，特别是锁的看门狗超时时间。
 *     同时，它也确保了只有在Redisson.class和RedisOperations.class存在于类路径中，且RedissonAutoConfiguration已经完成配置后，这个配置类才会被加载和配置。
 * <pre/>
 *
 * 关注公众号【奔跑的码畜】，一起进步不迷路
 *
 * @author 第七人格
 * @date 2024/06/17
 */
// 使用@Configuration注解，表示这是一个Spring Boot的配置类，用于定义Bean和配置信息
@Configuration
// @ConditionalOnClass注解表示仅当类路径中存在Redisson.class和RedisOperations.class时，此配置才会生效
@ConditionalOnClass({Redisson.class, RedisOperations.class})
// @AutoConfigureAfter注解表示此配置类应在RedissonAutoConfiguration配置类加载并配置完成后才进行加载配置
@AutoConfigureAfter({RedissonAutoConfiguration.class})
// @EnableConfigurationProperties注解启用DistributedLockProperties类的配置属性绑定
@EnableConfigurationProperties({DistributedLockProperties.class})
// @ComponentScan注解用于扫描并加载指定包下的组件，这里指定扫描包含DistributedLock.class的包
@ComponentScan(
        basePackageClasses = {DistributedLock.class}
)
public class DistributedLockRedissonAutoConfiguration {

    // 定义一个私有变量distributedLockProperties，其类型为DistributedLockProperties
    private final DistributedLockProperties distributedLockProperties;

    // 使用@Primary注解表示当存在多个同类型的Bean时，优先使用该Bean
    // 使用@Bean注解定义一个名为redissonClient的Bean，其类型为RedissonClient
    // destroyMethod属性指定在Bean销毁时调用的方法，这里指定为"shutdown"
    // @ConditionalOnBean注解表示仅当存在RedissonClient类型的Bean时，此Bean定义才会生效
    @Primary
    @Bean(
            name = {"redissonClient"},
            destroyMethod = "shutdown"
    )
    @ConditionalOnBean({RedissonClient.class})
    public RedissonClient redissonClient(RedissonClient redissonClient) {

        // 从传入的redissonClient中获取其配置
        Config config = redissonClient.getConfig();

        // 设置锁的看门狗超时时间，单位为毫秒，这里将distributedLockProperties中获取的锁超时时间（秒）转为毫秒
        config.setLockWatchdogTimeout(this.distributedLockProperties.getLockTimeout() * 1000L);

        // 关闭传入的redissonClient
        redissonClient.shutdown();

        // 使用更新后的配置创建一个新的RedissonClient实例并返回
        return Redisson.create(config);
    }

    // 构造函数，接收一个DistributedLockProperties类型的参数，用于初始化distributedLockProperties变量
    public DistributedLockRedissonAutoConfiguration(final DistributedLockProperties distributedLockProperties) {
        this.distributedLockProperties = distributedLockProperties;
    }
}
